package cn.xeblog.server.action.handler;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.xeblog.commons.entity.User;
import cn.xeblog.commons.entity.UserMsgDTO;
import cn.xeblog.commons.enums.MessageType;
import cn.xeblog.server.action.ChannelAction;
import cn.xeblog.server.action.specialAc.SpecialCommandHandler;
import cn.xeblog.server.action.specialAc.VoteActionEnum;
import cn.xeblog.server.action.timer.TimerAction;
import cn.xeblog.server.action.timer.TimerUtil;
import cn.xeblog.server.builder.ResponseBuilder;
import cn.xeblog.server.cache.UserCache;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author ZhangLei
 * @date 2024/2/5 14:34
 */
@Slf4j
public class VoteHandler2 {

    /**
     * 投票间隔 单位：秒
     */
    private static int VOTE_TIME_INTERVAL = 3 * 60;
    /**
     * 投票时间 单位：秒
     */
    private static int VOTE_TIME = 30;
    /**
     * 人数下限
     */
    private static int VOTE_USER_NUM = 3;

    /**
     * 缓存可投票的用户
     */
    private final static Map<String, User> voteMap = new HashMap<>();
    /**
     * 投票数据
     */
    private final static Map<String, String> voteResultMap = new HashMap<>();

    /**
     * 上次投票时间
     */
    public volatile static long lastVoteTime = 0;
    public volatile static boolean voteFlag = false;
    public volatile static int index = -1;
    public volatile static User candidate = null;

    private static void refreshConfig() {
        try {
            String json = FileUtil.readString("/home/xechat/config/config.json", StandardCharsets.UTF_8);
            JSONObject configObj = JSONObject.parseObject(json);

            JSONObject userKeys = configObj.getJSONObject("voteKeys");
            VOTE_TIME = userKeys.getIntValue("VOTE_TIME");
            VOTE_USER_NUM = userKeys.getIntValue("VOTE_USER_NUM");
            VOTE_TIME_INTERVAL = userKeys.getIntValue("VOTE_TIME_INTERVAL");
        } catch (Exception e) {
            log.info("投票配置解析异常！", e);
        }
    }

    public static void checkAndStartVote(User user, String[] split) {
        refreshConfig();

        long difference = System.currentTimeMillis() - lastVoteTime;
        if (difference / 1000 < VOTE_TIME_INTERVAL) {
            ChannelAction.send(ResponseBuilder.system("投票冷却中！不能重复发起！"));
            return;
        }

        if (UserCache.getActiveUserMap().size() < VOTE_USER_NUM) {
            ChannelAction.send(ResponseBuilder.system("投票未开启，活跃用户数量不足！至少需要" + VOTE_USER_NUM + "名活跃用户开启。"));
            return;
        }

        index = SpecialCommandHandler.checkIndex(user, split[1]);
        if (index < 0 || index >= VoteActionEnum.values().length) {
            ChannelAction.send(ResponseBuilder.system("无效选项，请重新检查！"));
            return;
        }

        VoteActionEnum voteActionEnum = VoteActionEnum.getByIndex(index);
        if (voteActionEnum == null) {
            ChannelAction.send(ResponseBuilder.system("无效选项，请重新检查！"));
            return;
        }

        candidate = UserCache.getUserByUsername(split[2]);
        if (candidate == null) {
            String tips = StrUtil.format("用户【{}】不存在", split[2]);
            ChannelAction.send(ResponseBuilder.system(tips));
            return;
        }

        String voteMsg = StrUtil.format("即将开起投票，本轮投票内容是【{}】，被执行的用户是【{}】。", voteActionEnum.getContent(), candidate.getUsername());
        ChannelAction.send(ResponseBuilder.system(voteMsg));

        startVote();
    }

    private static void initCache() {
        lastVoteTime = System.currentTimeMillis();
        voteMap.clear();
        voteMap.putAll(UserCache.getActiveUserMap().values().stream().collect(Collectors.toMap(User::getIp, Function.identity(), (k1, k2) -> k1)));
    }

    /**
     * 开启投票
     */
    public static void startVote() {

        // 初始化投票数据
        initCache();
        voteFlag = true;

        Set<String> collect = voteMap.values().stream().map(User::getUsername).collect(Collectors.toSet());
        String voteMsg = StrUtil.format("请在{}秒内，复制并发送【投票:::同意】或者【投票:::不同意】进行投票。本次有效投票用户：【{}】", VOTE_TIME, String.join("、", collect));
        ChannelAction.send(ResponseBuilder.system(voteMsg));

        TimerUtil.startTimer(new TimerAction() {
            @Override
            public void timingBegins(Date overTime) {
                long secondsLeft = (overTime.getTime() - new Date().getTime()) / 1000;
                List<Long> seconds = Lists.newArrayList(1L, 3L, 5L, 10L);
                if (secondsLeft % 20 == 0) {
                    String tips = StrUtil.format("投票进行中...剩余时间{}秒。", secondsLeft);
                    ChannelAction.send(ResponseBuilder.system(tips));
                } else if (seconds.contains(secondsLeft)) {
                    String tips = StrUtil.format("投票即将结束...剩余时间{}秒。", secondsLeft);
                    ChannelAction.send(ResponseBuilder.system(tips));
                }
            }

            @Override
            public void timingEnds(Date overTime) {
                doAction();
                index = -1;
                candidate = null;
            }
        }, VOTE_TIME);

    }

    private static void doAction() {
        // 清理无效投票
        voteResultMap.keySet().removeIf(k -> !voteMap.containsKey(k));
        if (voteResultMap.values().isEmpty()) {
            ChannelAction.send(ResponseBuilder.system("投票数据为空，无事发生。"));
            return;
        }

        VoteActionEnum voteActionEnum = VoteActionEnum.getByIndex(index);
        if (voteActionEnum == null) {
            ChannelAction.send(ResponseBuilder.system("无效选项，不执行任何操作！"));
            return;
        }

        long yes = voteResultMap.values().stream().filter("同意"::equals).count();
        long no = voteResultMap.values().stream().filter("不同意"::equals).count();

        String msg;
        if (yes < no) {
            msg = StrUtil.format("反对票居多，不执行任何操作！");
        } else {
            voteActionEnum.doAction(candidate);
            msg = StrUtil.format("即将执行的是【{}】，被执行的用户是【{}】", voteActionEnum.getContent(), candidate.getUsername());

        }
        String tips = StrUtil.format("投票结束！同意票数【{}】不同意票数【{}】。{}", yes, no, msg);
        ChannelAction.send(ResponseBuilder.system(tips));
    }

    public static void addVote(User user, UserMsgDTO body, String[] split) {
        if (!voteFlag) {
            user.send(ResponseBuilder.build(user, body, MessageType.USER));
            user.send(ResponseBuilder.system("非投票时间！无效操作！"));
            return;
        }

        if (!voteMap.containsKey(user.getIp())) {
            user.send(ResponseBuilder.build(user, body, MessageType.USER));
            user.send(ResponseBuilder.system("本次投票你暂无权限。"));
            return;
        }

        List<String> options = Lists.newArrayList("同意", "不同意");
        if (!options.contains(split[1])) {
            user.send(ResponseBuilder.build(user, body, MessageType.USER));
            user.send(ResponseBuilder.system("无效投票！请注意投票内容。"));
            return;
        }

        ChannelAction.send(user, body, MessageType.USER);
        voteResultMap.put(user.getIp(), split[1]);
    }

}
